package com.winchain.chainbill.bill.biz.transfer.service.impl;

import com.shell.bee.base.exception.UnCheckMsgException;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.entity.auth.AuthOrgan;
import com.shell.framework.utils.CommonDataUtil;
import com.winchain.chainbill.bill.base.po.CbOpt;
import com.winchain.chainbill.bill.base.po.CbRec;
import com.winchain.chainbill.bill.base.po.CbXfe;
import com.winchain.chainbill.bill.base.service.CbRecService;
import com.winchain.chainbill.bill.base.service.CbXfeService;
import com.winchain.chainbill.bill.biz.Bill;
import com.winchain.chainbill.bill.biz.BillEvent;
import com.winchain.chainbill.bill.biz.contract.rx.ContractSponsorSubscriber;
import com.winchain.chainbill.bill.biz.send.rx.BillAttSubscriber;
import com.winchain.chainbill.bill.biz.send.rx.BillMoveSubscriber;
import com.winchain.chainbill.bill.biz.send.rx.BillOptSubscriber;
import com.winchain.chainbill.bill.biz.send.rx.SetSellerTagSubscriber;
import com.winchain.chainbill.bill.biz.send.service.BillCheckService;
import com.winchain.chainbill.bill.biz.send.service.BillService;
import com.winchain.chainbill.bill.biz.send.vo.BatchBillStats;
import com.winchain.chainbill.bill.biz.transfer.rx.BillDfrlSubscriber;
import com.winchain.chainbill.bill.biz.transfer.rx.BillXfeAssetSubscriber;
import com.winchain.chainbill.bill.biz.transfer.rx.BillXfeChdSubscriber;
import com.winchain.chainbill.bill.biz.transfer.rx.BillXfeMsgSplitSubscriber;
import com.winchain.chainbill.bill.biz.transfer.rx.BillXfeMsgSubscriber;
import com.winchain.chainbill.bill.biz.transfer.rx.BillXfePrntSubscriber;
import com.winchain.chainbill.bill.biz.transfer.rx.BillXfeSubscriber;
import com.winchain.chainbill.bill.biz.transfer.service.BillXfeService;
import com.winchain.chainbill.bill.biz.transfer.vo.BillSplitEvent;
import com.winchain.chainbill.bill.biz.transfer.vo.BillXfe;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import rx.Observable;

@Service("billXfeService")
public class BillXfeServiceImpl implements BillXfeService {
	@Autowired
	private BillService billService;
	@Autowired
	private BillMoveSubscriber billMoveSubscriber;
	@Autowired
	private BillOptSubscriber billOptSubscriber;
	@Autowired
	private BillXfeSubscriber billXfeSubscriber;
	@Autowired
	private BillXfePrntSubscriber billXfePrntSubscriber;
	@Autowired
	private BillXfeChdSubscriber billXfeChdSubscriber;
	@Autowired
	private BillCheckService billCheckService;
	@Autowired
	private CbRecService cbRecService;
	@Autowired
	private BillDfrlSubscriber billDfrlSubscriber;
	@Autowired
	private BillXfeMsgSubscriber billXfeMsgSubscriber;
	@Autowired
	private BillXfeMsgSplitSubscriber billXfeMsgSplitSubscriber;
	@Autowired
	private BillXfeAssetSubscriber billXfeAssetSubscriber;
	@Autowired
	private ContractSponsorSubscriber<CbXfe> contractSponsorSubscriber;
	@Autowired
	private SetSellerTagSubscriber setSellerTagSubscriber;
	@Autowired
	private BillXfeRevServiceImpl billXfeRevService;
	@Autowired
	BillAttSubscriber billAttSubscriber;
	@Autowired
	private CbXfeService cbXfeService;

	public void transfer(String billId, String phoneCode, String location, CbXfe... xfes) {
		CbRec record = (CbRec) this.cbRecService.selectByKey(billId);

		String msg = this.billCheckService.checkBillXfe(record, xfes);
		if (StringUtil.notEmpty(msg)) {
			throw new UnCheckMsgException(msg);
		}
		List<BillXfe> bills = this.billService.init(record, xfes);

		int size = bills.size();
		if (size == 1) {
			xfe((BillXfe) bills.get(0));
		} else if (size > 1) {
			splitXfe(record, bills);
		}
		String cusType = CommonDataUtil.getCurEnt().getCusType();
		if (("PERSONAL".equals(cusType)) || ("SELF_EMPLOYED".equals(cusType))) {
			BatchBillStats<CbXfe> stats = this.billXfeRevService.pass(false, phoneCode, location,
					new String[] { billId });
			if (stats.getAffectedRows() == 0) {
				throw new UnCheckMsgException("������������");
			}
		}
	}

	public CbXfe selectOne(String billId, Integer hldrLvl, String sellerId) {
		CbXfe cbXfe = new CbXfe();
		cbXfe.setBillId(billId);
		cbXfe.setHldrLvl(hldrLvl);
		cbXfe.setSellerId(sellerId);
		return (CbXfe) this.cbXfeService.selectOne(cbXfe);
	}

	private void xfe(BillXfe bill) {
		BillEvent<CbXfe> event = new BillEvent(bill);
		CbOpt opt = new CbOpt();
		opt.setLimDate(((CbXfe) bill.getSource()).getXfeDate());
		opt.setCurState("S005");
		opt.setOptCode("E601");
		opt.setRemark("��������");

		CbXfe cbXfe = (CbXfe) bill.getSource();
		event.setOperation(opt);
		event.setValue("splitXfe", "false");
		event.setValue("bizId", cbXfe.getXfeId());
		event.setValue("invoiceNo", cbXfe.getInvoiceNo());
		event.setValue("sellerIds", cbXfe.getSellerId());

		event.setValue("attInvoices", cbXfe.getAttInvoicesJson());
		event.setValue("invType", "3");
		event.setValue("contractFileIds", cbXfe.getContractFileIds());

		Observable<BillEvent<CbXfe>> observers = Observable.just(event);
		observers.subscribe(this.billOptSubscriber);
		observers.subscribe(this.billXfeSubscriber);
		observers.subscribe(this.billMoveSubscriber);
		observers.subscribe(this.billDfrlSubscriber);
		observers.subscribe(this.billXfeMsgSubscriber);
		observers.subscribe(this.billXfeAssetSubscriber);
		observers.subscribe(this.billAttSubscriber);
		observers.subscribe(this.contractSponsorSubscriber);
		observers.subscribe(this.setSellerTagSubscriber);
	}

	private void splitXfe(CbRec record, List<BillXfe> bills) {
		Bill<CbXfe> prnt = new Bill();
		prnt.setRec(record);
		BillSplitEvent<CbXfe> event = new BillSplitEvent(prnt);
		event.setChildren(bills);

		CbOpt opt = new CbOpt();
		opt.setLimDate(((CbXfe) ((BillXfe) bills.get(0)).getSource()).getXfeDate());
		opt.setCurState("S005");
		opt.setOptCode("E201");
		opt.setRemark("��������");

		event.setOperation(opt);
		event.setValue("splitXfe", "true");

		event.setValue("invType", "3");

		List<String> sellerIds = new ArrayList();
		for (BillXfe xfe : bills) {
			if (xfe.getSource() != null) {
				sellerIds.add(((CbXfe) xfe.getSource()).getSellerId());
			}
		}
		event.setValue("sellerIds", String.join(",", sellerIds));

		Object observers = Observable.just(event);
		((Observable) observers).subscribe(this.billXfePrntSubscriber);
		((Observable) observers).subscribe(this.billXfeChdSubscriber);
		((Observable) observers).subscribe(this.billXfeMsgSplitSubscriber);
		((Observable) observers).subscribe(this.billXfeAssetSubscriber);
		((Observable) observers).subscribe(this.setSellerTagSubscriber);
	}
}
